﻿using FySystem.Extension;
using FySystem.IO;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Reflection;
using System.Text;
using System.Threading.Tasks;

namespace FySystem.Net.LSTP.MC
{
    public class LSTPMCBase
    {
        public IPAddress IP { get; set; }

        public int Port { get; set; }

        internal Dictionary<string, RouterInfo> Routers { get; set; } = null;

        /// <summary>
        /// 通过反射获取所有控制器
        /// </summary>
        protected void GetControllers()
        {
            try
            {
                Routers = new Dictionary<string, RouterInfo>();

                string name = Assembly.GetEntryAssembly().GetName().Name;
                string path = AppDomain.CurrentDomain.BaseDirectory + name + ".dll";
                Assembly assembly = Assembly.LoadFrom(path);
                Type[] types = assembly.GetTypes();

                if (types != null)
                {
                    foreach(var type in types)
                    {
                        if(type.BaseType != null)
                        {
                            if(type.BaseType.Name == "LSTPControllerBase")
                            {
                                string controllerName = type.Name;
                                int index = controllerName.LastIndexOf("Controller");
                                if (index != -1)
                                    controllerName = controllerName.Substring(0, index).ToLower();

                                //遍历控制器中的所有函数
                                var methods = type.GetMethods();

                                if (methods != null)
                                {
                                    foreach(var method in methods)
                                    {
                                        if (method.GetCustomAttributes(typeof(LSTPApiAttribute)).IsNullOrEmpty() == false)
                                        {
                                            Routers.Add($"/{controllerName}/{method.Name.ToLower()}", new RouterInfo()
                                            {
                                                ControllerType = type,
                                                Method = method
                                            });
                                        }
                                    }
                                }
                            }
                        }
                    }
                }
            }
            catch (Exception)
            {
                throw;
            }
        }

        /// <summary>
        /// 查找路由
        /// </summary>
        /// <param name="router"></param>
        /// <returns></returns>
        /// <exception cref="NotImplementedException"></exception>
        internal RouterInfo FindRouter(string router)
        {
            RouterInfo res = null;
            try
            {
                router = router.ToLower();
                Routers.TryGetValue(router, out res);
            }
            catch (Exception)
            {
                throw;
            }
            return res;
        }

        /// <summary>
        /// 收到请求，由于目前cson没有序列化和反序列化，所以接口的参数只能是cson，返回结果只能是cson
        /// </summary>
        /// <param name="request"></param>
        /// <param name="response"></param>
        /// <exception cref="NotImplementedException"></exception>
        protected void OnRequest(LSTPRequest request, LSTPWebResponse response)
        {
            try
            {
                RouterInfo routerInfo = FindRouter(request.Router);
                if (routerInfo == null)
                {
                    response.WriteInterError(-1, "未找到路由~");
                }
                else
                {
                    try
                    {
                        //用反射创建Controller类
                        LSTPControllerBase controller = (LSTPControllerBase) Activator.CreateInstance(routerInfo.ControllerType);

                        //给基类的属性设置值
                        controller.Request = request;
                        controller.Response = response;
                        object result = null;

                        if (routerInfo.Method.GetParameters().IsNullOrEmpty())
                            result = routerInfo.Method.Invoke(controller, null);
                        else
                            result = routerInfo.Method.Invoke(controller, new object[] { request.Body });
                        CSon cResult = null;
                        if (result != null)
                        {
                            //如果函数有返回值
                            cResult = (CSon)result;
                        }
                        else
                        {
                            cResult = CSon.CSonObjectNull;
                        }

                        response.Write(cResult);
                    }
                    catch (Exception ex)
                    {
                        response.WriteError(1, ex.Message);
                    }
                }
            }
            catch (Exception ex)
            {
                FyLogContext.Write(ex.Message);
            }
        }
    }
}
